package jp.wug.core;

import com.google.inject.TypeLiteral;
import jp.wug.WugRequest;
import jp.wug.util.QueryParameters;

import javax.inject.Provider;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.ResourceBundle;

public class Page {
    final Model model;
    private final Writable writable;
    private final ControllerFactory.Controller controller;
    private final PageFactory.RequestURLParser requestURLParser;
    private final Provider<WugRequest> wugRequestProvider;

    Page(Model model, Writable writable, PageFactory.RequestURLParser requestURLParser, ControllerFactory.Controller controller, Provider<WugRequest> wugRequestProvider) {
        this.model = model;
        this.writable = writable;
        this.requestURLParser = requestURLParser;
        this.controller = controller;
        this.wugRequestProvider = wugRequestProvider;
    }

    public List<ModelException> fill(WugRequest request) {
        return requestURLParser.fill(model, request);
    }

    public void action(String action, WugRequest request) {
        controller.action(model, action);
    }

    public void post(WugRequest request) {
        boolean hasException = controller.fillForm(model, request);
        if (!hasException) {
            controller.submitForm(model, request);
        }
    }

    public void write(Writer writer) throws IOException {
        WritableContext context = new WritableContext(this, model, controller);
        context = context.push(new TypeLiteral<Provider<ResourceBundle>>() {
        }, wugRequestProvider.get().getResourceBundleProvider());
        writable.write(writer, context);
    }

    public void writeExported(Writer writer, WritableContext context) throws IOException {
        writable.write(writer, context);
    }

    public void dump(Writer writer) throws IOException {
        WritableContext context = new WritableContext(this, model, controller);
        context = context.push(new TypeLiteral<Provider<ResourceBundle>>() {
        }, wugRequestProvider.get().getResourceBundleProvider());
        writable.write(new NullWriter(), context);
        context.dump(writer);
    }


    public String toPathInfoPlusQueryParameter() {
        WugRequest request = wugRequestProvider.get();
        QueryParameters queryParameter = new QueryParameters(request.getContextPathPlusServletPath());
        request.appendURLParameters(queryParameter);
        requestURLParser.appendURLParameters(model, queryParameter);
        return queryParameter.toPath();
    }

    String toPathInfoPlusQueryParameterByModel() {
        WugRequest request = wugRequestProvider.get();
        QueryParameters queryParameter = new QueryParameters(request.getContextPathPlusServletPath());
        request.appendURLParameters(queryParameter);
        requestURLParser.appendURLParameters(model, queryParameter);
        return queryParameter.toPath();
    }

    public String toPathInfoPlusQueryParameterForActionByModel(String pathArgs) {
        WugRequest request = wugRequestProvider.get();
        QueryParameters queryParameter = new QueryParameters(request.getContextPathPlusServletPath());
        request.appendURLParameters(queryParameter);
        queryParameter.append("_action", pathArgs);
        requestURLParser.appendURLParameters(model, queryParameter);
        return queryParameter.toPath();
    }

    public String toPathInfoPlusQueryParameterForFormByModel() {
        WugRequest request = wugRequestProvider.get();
        QueryParameters queryParameter = new QueryParameters(request.getContextPathPlusServletPath());
        request.appendURLParameters(queryParameter);
        requestURLParser.appendURLParameters(model, queryParameter);
        return queryParameter.toPath();
    }

    private static class NullWriter extends Writer {
        @Override
        public void write(char[] buffer, int off, int len) {
        }

        @Override
        public void flush() {
        }

        @Override
        public void close() {
        }
    }
}